iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 8
1

前言

這篇開始,會陸續分享一些資料處理上碰到的狀況和處理經驗,已上線系統來說,資料的完整和正確性優先權也幾乎是最高,一但發生問題,損失難以估計。

相較程式crash,資料有或錯可能是更大的痛苦,以過來經驗補資料可能幾個小時,甚至從晚上持續到凌晨不等,還不如程式直接crash,不過真的直接crash也會被巴死就是了。

首先想聊聊map和slice塞資料遇到的問題。

這篇比較像說故事,說說造就問題是因為自己的無知,卻還以為是別人問題的故事。

問題發生

如果有使過多個goroutine對同一個map寫入資料,那麼會知道前後加上lock,避免發生fatal error。

除了避免發生fatal error導致程式crash,保護資料的正確性也是相當重要的,相關說明FAQ也找得到,有goroutine使用的map加上lock完全無掛礙。

那時候為了debug和計數,有發現裡面的int變數不放在lock裡面,會有race condition的問題,不會報error、panic或fatal error,但數值會不正確。

於是就很愉快地把這個int變數放在lock和unlock之間,輕鬆愉快。

我的缺失,在於看到這個int數值有錯漏的時候,沒有多想想其他類似的相關應用,只想解決計數用的變數數值不正確這檔事。

系統上線莫約20天,處理量越來越大的時候,夜路走多終於遇到鬼,某塊資料少了一大片,log沒有記錄到程式上的任何錯誤,當下認為是別部門回傳的API資料有少,猜想是API回傳的http status 是200但內容沒資料,非常森77,當下除了辛苦補資料,還加上寫了該API回傳內容的log,一次可能有好幾萬筆資料,但有紀錄才能找他們處理。

真相

大約又過了20多天,這期間狀況沒有重現,也因此沒放在心上,反正出事有log唄,在開發新專案的時候,我們發現了一個奇怪的問題。

為什麼我們做壓測到某個數量級的時候,最後出來資料就會有少?追蹤後,發現起源在於儲存API的回來資料的slice有缺。

因為slice前後沒加lock,API的資料又是使用goroutine分別去要回來,收集到這個slice。

加slice的資料是用append的方式,我不曉得是不是因為這樣的關係,大約經過了40天,經手了百萬筆資料的處理,才發生過一次race condtition,導致資料有錯誤。

結論是只要有多個goruinte寫入共同的變數,無論對象是什麼資料結構,都要加上lock才好確保安全,雖然FAQ沒有特別提這塊,程式也不會報錯或crash。

至此才又重新認識一遍concurrency的goroutine,原來教科書裡面,好像很理論的race condition就很現實很容易的發生在你我身邊,對於goroutine處理的資料,再謹慎也不為過。


上一篇
Day7 .[重災經驗篇] 爆連線問題,TCP ESTABLISHED 咬著不放
下一篇
Day9 .[正確資料篇] range、map、slice、channel、goroutine 的組合應用
系列文
Let's Eat GO ! 實務開發雜談by Golang30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言